package jkws

import (
	"crypto/tls"
	"jkgo/jk/jklog"
	"strconv"
	"time"

	"golang.org/x/net/websocket"
)

// CMWSHandlerClient handler
type CMWSHandlerClient struct {
	addr      string
	port      int
	conn      *websocket.Conn
	secure    bool
	baseurl   string
	fullurl   string
	originurl string
}

// NewWSHandlerClient create ws handler client
func NewWSHandlerClient(addr string, port int, secure bool, baseurl string) (*CMWSHandlerClient, error) {
	ws := &CMWSHandlerClient{
		addr:   addr,
		port:   port,
		secure: secure,
	}
	header := "ws://"
	headerOrig := "http://"
	if secure {
		header = "wss://"
		headerOrig = "https://"
	}

	ws.fullurl = header + addr + ":" + strconv.Itoa(port) + "/" + baseurl
	ws.originurl = headerOrig + addr + ":" + strconv.Itoa(port) + "/" + baseurl

	return ws, nil
}

// Connect retry count (interval 1 second)
func (ws *CMWSHandlerClient) Connect(retry int) error {
	var err error
	for i := 0; i < retry; i++ {
		ws.conn, err = websocket.Dial(ws.fullurl, "", ws.originurl)

		if err != nil {
			jklog.L().Errorln(err)
		} else {
			return nil
		}
		time.Sleep(time.Second * 1)
	}

	return err
}

func (ws *CMWSHandlerClient) ConnectTls(retry int) error {
	jklog.L().Infoln("connect to ", ws.fullurl)
	var err error
	config, err := websocket.NewConfig(ws.fullurl, ws.originurl)
	if err != nil {
		jklog.L().Errorln(err)
		return err
	}
	config.TlsConfig = &tls.Config{
		InsecureSkipVerify: true,
	}
	for i := 0; i < retry; i++ {
		ws.conn, err = websocket.DialConfig(config)

		if err != nil {
			jklog.L().Errorln(err)
		} else {
			return nil
		}
		time.Sleep(time.Second * 1)
	}

	return err
}

// Close close handler
func (ws *CMWSHandlerClient) Close() {
	ws.conn.Close()
}

// Recv recv data
func (ws *CMWSHandlerClient) Recv(msg []byte) (int, error) {
	return ws.conn.Read(msg)
}

// Send send data, @recv if recv response
func (ws *CMWSHandlerClient) Send(msg []byte, recv bool) (int, error) {
	jklog.L().Debugln("Write data to ", string(msg))
	n, err := ws.conn.Write(msg)
	if err != nil {
		jklog.L().Errorln(err)
		return 0, err
	}
	if recv {
		dd := make([]byte, 10240)
		var x int
		for {
			x, err = ws.Recv(dd)
			if err != nil {
				break
			} else {
				jklog.L().Infoln("recv data : ", string(dd[:x]))
			}
		}
		jklog.L().Infoln("response data: ", string(dd[:x]))
	}
	return n, err
}
